package p.ithorns.framework.logger.websocket;

import io.netty.channel.Channel;
import io.netty.channel.ChannelId;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.concurrent.GlobalEventExecutor;
import org.springframework.util.StringUtils;

import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadLocalRandom;

/**
 * WsSupervise
 * TODO
 *
 * @author ithorns
 * @version 1.0.0
 * @date 2023/3/10 10:04
 */
public class WsSupervise {

    /**
     * Channel组
     *
     * ImmediateEventExecutor.INSTANCE
     */
    private static ChannelGroup globalGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    /**
     * Client -> Channel
     */
    private final static ConcurrentHashMap<String, ChannelId> CLIENT_ID_MAP = new ConcurrentHashMap<>();

    /**
     * Channel -> Client
     */
    private final static ConcurrentHashMap<ChannelId, String> CHANNEL_ID_MAP = new ConcurrentHashMap<>();


    /**
     * 注册客户端Channel
     *
     * @param clientId -客户端ID
     * @param channel  -Channel
     */
    public static void register(String clientId, Channel channel) {
        if (!StringUtils.hasText(clientId)) {
            return;
        }

        ChannelId channelId = channel.id();

        Channel chan = globalGroup.find(channelId);
        if (null == chan) {
            globalGroup.add(channel);
        }

        // 客户端Channel双向映射
        CLIENT_ID_MAP.put(clientId, channelId);
        CHANNEL_ID_MAP.put(channelId, clientId);
    }

    /**
     * 通过Channel查询客户端ID
     *
     * @param id -Channel ID
     * @return String 客户端ID
     */
    public static String getClient(ChannelId id) {
        return CHANNEL_ID_MAP.get(id);
    }

    /**
     * 移除Channel
     *
     * @param channel -
     */
    public static void removeChannel(Channel channel) {
        globalGroup.remove(channel);

        String clientId = CHANNEL_ID_MAP.get(channel.id());
        if (clientId != null) {
            CLIENT_ID_MAP.remove(clientId);
            CHANNEL_ID_MAP.remove(channel.id());
        }
    }


    /**
     * 指定客户端发送Json消息
     *
     * @param clientId -客户端ID
     * @param json     -Json消息
     */
    public static void sendToSimple(String clientId, String json) {
        Optional.ofNullable(CLIENT_ID_MAP.get(clientId.toLowerCase()))
                .ifPresent(id -> {
                    Channel channel = globalGroup.find(id);
                    if (null != channel) {
                        channel.writeAndFlush(new TextWebSocketFrame(json));
                    }
                });
    }


    /**
     * 广播
     */
    public static void sendToAll(String json) {
        if (globalGroup.size() > 0) {
            int i = ThreadLocalRandom.current().nextInt(1000);
            if (i % 7 == 0) {
                try {
                    Thread.sleep(2);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            globalGroup.writeAndFlush(new TextWebSocketFrame(json));
        }
    }

}